<!---
	Copyright 2010 Edward Trudeau, Jeremy Battle
    This software is freely available under the MIT License: http://www.opensource.org/licenses/mit-license.php
    http://ayc.googlecode.com
    
--->

<!--- authenticator.cfc
	CFC loads and manages application security, checks for permissions, etc.
	created 23 July 07 EJT
	
	NOTES:
	
	 --->


<cfcomponent displayname="Authenticator" hint="Manages login authentication and permissions">
	<!--- properties --->
	<cfproperty name="config" type="configurator" hint="Hold application level configuration information" />
	
	<cfset variables.config = "" />
    <cfset variables.userService = "" />
	
	<cffunction name="init" access="public" returntype="Authenticator">
		<cfargument name="configurator" type="configurator" required="yes" hint="Application configuration struct" />
		<cfset variables.config = arguments.configurator.config />
		
		<cfreturn this />
	</cffunction>
    
    <cffunction name="setUserService" returntype="void" access="public" output="no">
    	<cfargument name="userService" type="User.UserService" required="yes" />
        
        <cfset variables.userService = arguments.userService />
    </cffunction>
	
	<cffunction name="doLogin" displayname="doLogin" hint="Decides which login option to use and invokes the corresponding function" returntype="boolean">
		<cfargument name="username" type="string" required="yes" />
		<cfargument name="password" type="string" required="yes" />
        <cfargument name="loginType" type="string" required="yes" />
		
		<cfswitch expression="#arguments.loginType#">
			<cfcase value="db">
				<cfreturn dbLogin(arguments.username, arguments.password) />
			</cfcase>
			<cfcase value="ldap">
				<cfreturn ldapLogin(arguments.username, arguments.password, variables.config.authDomain) />
			</cfcase>
			<cfdefaultcase>
				<cfthrow message="Authenticator.doLogin.invalidAuthType" detail='The value of authStore located in the config file ("#variables.config.authStore#") is not a valid type.' />
				<cfreturn false />
			</cfdefaultcase>
		</cfswitch>
		
	</cffunction>
	
	<cffunction name="ldapLogin" displayname="ldapLogin" hint="Manages login to the application" returntype="boolean">
		<cfargument name="username" type="string" required="yes" />
		<cfargument name="password" type="string" required="yes" />
		<cfargument name="domain" type="string" required="no" default="CUA" />
		
		<cfswitch expression="#arguments.domain#">
			<cfdefaultcase>
				<cftry>
					<cfhttp url="https://secure.cua.edu/utils/ldap.cfm" port="443" method="post" delimiter="," resolveurl="no" throwonerror="yes" timeout="#createTimeSpan(0,0,0,20)#">
						<cfhttpparam type="formfield" name="username" value="#arguments.username#" />
						<cfhttpparam type="formfield" name="password" value="#arguments.password#" />
					</cfhttp>
					
					<cfif cfhttp.statusCode DOES NOT CONTAIN "200">
						<cfthrow type="LDAPNotReady" />
					</cfif>
					
					<cfif trim(cfhttp.FileContent ) NEQ "1">
						<cfreturn false />
					<cfelse>
						<cfreturn true />
					</cfif>
					
					<cfcatch type="LDAPNotReady">
						<cfthrow type="Authenticator.doLogin.LDAPNotReady" message="Authenticator.doLogin LDAP server returned a failure code: #cfhttp.statusCode#" />
					</cfcatch>
					
					<cfcatch type="any">
						<cfthrow type="Authenticator.doLogin.LDAPFailure" message="Authenticator.doLogin failed to hit the ldap server - timed out?" />
					</cfcatch>
				</cftry>
			</cfdefaultcase>
		</cfswitch>
		
		
	</cffunction>
	
	<cffunction name="dbLogin" displayname="dbLogin" hint="Manages login to the application using database values" returntype="boolean">
		<cfargument name="username" type="string" required="yes" />
		<cfargument name="password" type="string" required="yes" />
		
		<cfset var aUsers = "" />
        <cfset aUsers = variables.userService.getUsers(username=arguments.username,password=arguments.password,authType="db",active=1,banned=0) />
		
		<cfif NOT arrayLen(aUsers) OR compare(aUsers[1].getPassword(), trim(arguments.password)) NEQ 0>
			<cfreturn false />
		<cfelse>
			<cfreturn true />
		</cfif>		
	</cffunction>
	
</cfcomponent>

